<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		* {
			padding: 0;
			margin: 0;
		}
		#canvas {
			border: 1px solid #333;
			width: 800px;
			height: 600px;
			top: 50%;
			margin-left: 50%;
			transform: translate(-50%, -60%);
			position: absolute;

		}
	</style>
</head>
<body>
	<canvas id="canvas" width="800" height="600"></canvas>
	<script>
		// 贪食蛇速度
		let speed = 500
		// 定义一个全局的是否吃到食物的一个变量
		let isEatFood = false
		// 获取画布
		const canvas = document.getElementById('canvas')
		const ctx = canvas.getContext('2d')

		// 基础小方格构建食物和贪食蛇
		class Rect {
			constructor(x, y, width, height, color) {
				this.x = x
				this.y = y
				this.width = width
				this.height = height
				this.color = color
			}
			draw() {
				ctx.beginPath()
				ctx.fillStyle = this.color
				ctx.fillRect(this.x, this.y, this.width, this.height)
				ctx.strokeRect(this.x, this.y, this.width, this.height)
			}
		}

		// 蛇
		class Snake {
			// 蛇头，蛇身，蛇长, 方向
			constructor(length = 0) {
				this.direction = 2;
				this.length = length;
				this.head = new Rect(canvas.width / 2, canvas.height / 2 - 20, 40, 40, 'red');
				this.body = new Array(length).fill().map((i, idx) =>
					new Rect(this.head.x - 40 * (idx + 1), this.head.y, 40, 40, 'yellow')
				)
			}
			// 画蛇
			drawSnake() {
				// 如果碰到了
				if (this.isHit()) {
					// 清除定时器
					// clearInterval(timer)
					const con = confirm(`总共吃了${this.body.length - this.length}个食物，重新开始吗`)
					// 是否重开
					if (con) {
						draw()
					}
					return
				}
				// 绘制蛇头
				this.head.draw();
				// 绘制蛇身
				this.body.forEach(it => it.draw());
			}
			isHit() {
				const head = this.head
				// 是否碰到左右边界
				const xLimit = head.x < 0 || head.x >= canvas.width
				// 是否碰到上下边界
				const yLimit = head.y < 0 || head.y >= canvas.height
				// 是否撞到蛇身
				const hitSelf = this.body.find(({ x, y }) => head.x === x && head.y === y)
				// 三者其中一个为true则游戏结束
				return xLimit || yLimit || hitSelf
			}
			// 蛇移动
			moveSnake() {
				// 将蛇头上一次状态，拼到蛇身首部
				const rect = new Rect(this.head.x, this.head.y, this.head.width, this.head.height, 'yellow')
				this.body.unshift(rect)

				// 判断蛇头是否与食物重叠，重叠就是吃到了，没重叠就是没吃到
				isEatFood = food && this.head.x === food.x && this.head.y === food.y

				// 判断是否吃到食物
				if (!isEatFood) {
					this.body.pop()
				} else {
					const newFood = randomFood(this)
					food.x = newFood.x;
					food.y = newFood.y;
					food.draw()
					isEatFood = false
				}

				// 根据方向，控制蛇头的坐标
				switch (this.direction) {
					case 0:
						this.head.x -= this.head.width
						break
					case 1:
						this.head.y -= this.head.height
						break
					case 2:
						this.head.x += this.head.width
						break
					case 3:
						this.head.y += this.head.height
						break
				}
			}
		}

		// 建立蛇实例
		const snake = new Snake(3);
		// 建立随机食物实例
		const food = randomFood(snake);
		// 随机食物
		function randomFood(snake) {
			let isInSnake = true
			let rect
			while (isInSnake) {
				const x = Math.round(Math.random() * (canvas.width - 40) / 40) * 40
				const y = Math.round(Math.random() * (canvas.height - 40) / 40) * 40
				rect = new Rect(x, y, 40, 40, 'blue')
				// console.log(x,y);
				// 判断食物是否与蛇头蛇身重叠
				if ((snake.head.x === x && snake.head.y === y) || snake.body.find(item => item.x === x && item.y === y)) {
					isInSnake = true
					continue
				} else {
					isInSnake = false
				}
			}
			return rect;
		}

		function draw() {
			snake.drawSnake()
			food.draw()
			const timer = setInterval(() => {
				ctx.clearRect(0, 0, canvas.width, canvas.height)
				snake.moveSnake()
				snake.drawSnake()
				food.draw()
			}, speed)

		}
		// 键盘事件
		document.onkeydown = function (e) {
			console.log(37)
			e = e || window.event
			// 左37  上38  右39  下40
			switch (e.keyCode) {
				case 37:
					// console.log(37)
					// 三元表达式，防止右移动时按左，下面同理(贪吃蛇可不能直接掉头)
					snake.direction = snake.direction === 2 ? 2 : 0
					snake.moveSnake()
					break
				case 38:
					// console.log(38)
					snake.direction = snake.direction === 3 ? 3 : 1
					break
				case 39:
					// console.log(39)
					snake.direction = snake.direction === 0 ? 0 : 2
					break
				case 40:
					// console.log(40)
					snake.direction = snake.direction === 1 ? 1 : 3
					break

			}
		}

		window.onload = () => {
			draw();
		}
	</script>
</body>
</html>